var express = require('express');
const path = require('path');
var app = express.Router();

const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
Grid.mongo = mongoose.mongo;
const conn = mongoose.connection;

// 引入Http状态码
const { StatusCodes } = require('http-status-codes');
var { File, Comment, Reply, three } = require('../mondules/csy/csy_module')
var { loginModel } = require('../mondules/fu/fu_module')
// 引入 fs-extra 模块处理文件系统
const fs = require("fs-extra");
// 定义每个文件块的大小
const CHUNK_SIZE = 100 * 1024 * 1024;

//初始化Gridfs



// 定义公共文件夹的路径 
const PUBLIC_DIR = path.resolve(__dirname, "..", "uploads");
// 定义临时文件夹的路径 
const TEMP_DIR = path.resolve(__dirname, "temp");
// 确保公共文件夹存在 
fs.ensureDirSync(PUBLIC_DIR);
// 确保临时文件夹存在 
fs.ensureDirSync(TEMP_DIR);

//初始化GridFs


// 获取文件信息
app.post('/upload/:fileName', async (req, res, next) => {  // 添加 next 作为参数
    try {
        const { fileName } = req.params;
        const { chunkFileName } = req.query;
        const chunkDir = path.resolve(TEMP_DIR, fileName);
        // 分片的路径
        const chunkFilePath = path.resolve(chunkDir, chunkFileName);
        //写入文件的起始位置
        //从查询参数中获取起始位置，如果不是数字则默认为0
        const start = isNaN(req.params.start) ? 0 : parseInt(req.params.start, 10);
        // 确保分片文件夹存在
        await fs.ensureDirSync(chunkDir);
        // 创建此文件的可写流
        const ws = fs.createWriteStream(chunkFilePath, { start, flags: "a" });

        // 如果请求被中断，关闭可写流
        req.on('upload', () => {
            ws.close();
        });

        // 管道流写入可写流
        await pipeStream(req, ws);

        res.status(StatusCodes.OK).send({
            success: true,
            message: '文件上传成功'
        });

    } catch (error) {
        // 捕获并传递错误给下一层中间件处理
        next(error);
    }
});


// 定义管道流函数
function pipeStream(rs, ws) {
    return new Promise((resolve, reject) => {
        rs.pipe(ws).on('finish', resolve).on('error', reject);
    });
}



//处理合并文件的请求
app.post('/merge', async (req, res, next) => {
    const fileName = req.body.fileName;
    try {
        await mergeChunks(fileName);
        const filePath = + fileName;

        res.send({
            success: true,
            message: '文件合并成功',
        })
    } catch (error) {
        next(error);
    }
})

//添加发布内容
app.post('/add', async (req, res, next) => {
    const data = req.body;
    console.log(data);

    File.create(data).then(rep => {
        res.send({
            code: 200,
            message: '发布成功',
            data: {
                id: rep._id,
                text: rep.text,
                textarea: rep.textarea,
                path: 'http://localhost:3333/uploads/' + rep.path,
            }
        })
    })
})

// 定义合并分片文件的函数
async function mergeChunks(fileName) {
    //定义一个合并后的文件路径
    const mergedFilePath = path.resolve(PUBLIC_DIR, fileName);
    const chunkDir = path.resolve(TEMP_DIR, fileName)
    //读取文件 返回一个分片文件对应的数组
    const chunkFiles = await fs.readdir(chunkDir)

    //对分片按索引进行排序
    chunkFiles.sort((a, b) => Number(a.split("-")[1]) - Number(b.split("-")[1]))
    //合并所有分片文件
    //chunkFile 分片文件路径 ：index 分片索引
    const pipes = chunkFiles.map((chunkFile, index) => {
        //第一个参数 可读流，第二个参数，可写流
        return pipeStream(
            // autoclose ：true 写入之后字段关闭该可读流
            fs.createReadStream(path.resolve(chunkDir, chunkFile), {
                autoClose: true
            }),
            fs.createWriteStream(mergedFilePath, {
                start: index * CHUNK_SIZE
            })
        )
    });
    //并发将每个分片的数据写入到目标文件中去
    await Promise.all(pipes)
    //删除分片的文件和文件夹
    await fs.rm(chunkDir, { recursive: true })

}

//处理文件验证请求
app.post('/verify', async (req, res, next) => {
    try {
        // 从请求参数中获取文件名
        const fileName = req.body.fileName;
        // 判断文件是否已经存在
        const filePath = path.resolve(PUBLIC_DIR, fileName);
        const exisFile = await fs.pathExists(filePath);

        if (exisFile) {
            return res.send({
                code: 200,
                message: '文件已存在',
                needUpload: false,  // 文件已存在，则不需要上传

            });
        }

        // 如果文件不存在，返回文件不存在的响应
        const tempDir = path.resolve(TEMP_DIR, fileName);
        const exisDir = await fs.pathExists(tempDir);

        // 存放已上传的分片对象数组
        let uploadedChunkList = [];
        if (exisDir) {
            const chunkFiles = await fs.readdir(tempDir);
            uploadedChunkList = await Promise.all(
                chunkFiles.map(async (file) => {
                    const stat = await fs.stat(path.resolve(tempDir, file));
                    return { chunkFileName: file, size: stat.size };
                })
            );
        }
        res.send({
            success: true,
            needUpload: uploadedChunkList.length === 0,  // 如果没有分片，表示需要上传
            uploadedChunkList,

        });
    } catch (error) {
        console.error('Error in file verification:', error);
        next(error);  // 捕获错误并传递给下一个中间件
    }
});

//查找特定的数据
app.post('/one', async (req, res, next) => {
    let { id } = req.body;
    try {
        const data = await File.findOne({ _id: id });
        if (!data) {
            return res.status(404).json({ message: 'File not found' });
        }
        // 查找与文件相关联的用户
        const user = await loginModel.findOne({ _id: data.user });
        if (!user) {
            return res.status(404).json({ message: 'User not found' });
        }
        res.send({
            code: 200,
            data: {
                id: data._id,
                text: data.text,
                textarea: data.textarea,
                user: user.phone,
                path: 'http://localhost:3333/uploads/' + data.path,
                flag: data.flag,
                like: data.like,
            }
        });
    } catch (error) {
        console.error('Error in file verification:', error);
        next(error);  // 捕获错误并传递给下一个中间件
    }
})

//查找所有的数据
app.get('/all', async (req, res, next) => {
    try {
        const files = await File.find().populate('user');  // 获取所有文件并填充关联的 'user' 信息
        const formattedFiles = files.map(file => ({
            _id: file._id,
            text: file.text,
            textarea: file.textarea,
            user: file.user,  // user 是通过 populate 填充的，包含用户信息
            path: 'http://localhost:3333/uploads/' + file.path,  // 拼接文件的路径
            flag: file.flag,
            like: file.like,
        }));
        res.send({
            code: 200,
            data: formattedFiles,  // 返回格式化后的文件数组
        });
    } catch (error) {
        console.error('获取文件时发生错误:', error);
        next(error);
    }
});

//添加评论
app.post('/comment', async (req, res, next) => {
    let data = req.body
    console.log(data);
    try {
        Comment.create({ ...data }).then(rep => {
            res.send({
                code: 200,
                data: rep
            })
        })
    } catch (error) {
        console.error('Error in file verification:', error);
        next(error);  // 捕获错误并传递给下一个中间件
    }
})

//给评论回复
app.post('/reply', async (req, res, next) => {
    let data = req.body
    Reply.create({
        user: data.user,
        content: data.content,
        target_callId: data.target_callId,
        self_callId: data.self_callId
    }).then(rep => {
        res.send({
            code: 200,
            data: rep
        })
    })
});

//添加三级评论
app.post('/addthree', async (req, res, next) => {
    let data = req.body
    console.log(data);
    try {
        three.create({ ...data }).then(rep => {
            res.send({
                code: 200,
                data: rep
            })
        })
    } catch (error) {
        console.error('Error in file verification:', error);
        next(error);  // 捕获错误并传递给下一个中间件
    }
})




app.get('/getcomments', async (req, res, next) => {
    let id = req.query.id
    try {
        // 获取所有评论并填充 user 和 article 数据
        const comments = await Comment.find({ article: id })
            .populate({
                path: 'user',
                select: 'phone'  // 只选择 phone 字段
            })
            .populate({
                path: 'article',
                select: 'text'  // 只选择 text 字段
            })
            .exec();
        // 填充每个评论的回复数据
        for (let comment of comments) {
            const replies = await Reply.find({
                target_callId: comment._id  // 查找属于该评论的回复
            }).populate({
                path: 'user',
                select: 'phone'  // 只选择 phone 字段
            })
                .populate({
                    path: 'target_callId',
                    select: 'content'  // 只选择 phone 字段
                })
                .exec();
            // 将回复数据赋值给评论
            comment.replies = replies;
        }
        //为第二级评论填充回复数据
        for (let comment of comments) {
            for (let reply of comment.replies) {
                const replies = await three.find({
                    target_callId: reply._id  // 查找属于该评论的回复
                }).populate({
                    path: 'user',
                    select: 'phone'  // 只选择 phone 字段
                })
                    .populate({
                        path: 'target_callId',
                        select: 'content'  // 只选择 phone 字段
                    })
                    .exec();
                // 将回复数据赋值给评论
                reply.replies = replies;
            }
        }
        // 返回评论和回复数据到客户端
        res.send({
            code: 200,
            data: comments
        })  // 将数据以 JSON 格式发送给前端
    } catch (error) {
        console.error('Error in file verification:', error);
        next(error);  // 捕获错误并传递给下一个中间件
    }
});


//给文章点赞在请求一次就取消点赞
app.post('/like', async (req, res, next) => {
    try {
        const data = req.body;
        if (!data.id) {
            return res.status(400).send({ message: '文件 ID 是必需的' });
        }

        // 先查找文件
        const file = await File.findOne({ _id: data.id });

        if (!file) {
            return res.status(404).send({ message: '文件未找到' });
        }

        // 更新文件的 like 字段
        const updatedFile = await File.findOneAndUpdate(
            { _id: data.id },
            {
                $set: {
                    flag: data.flag,
                    like: data.flag ? (file.like || 0) + 1 : (file.like || 0) - 1
                }
            },
            { new: true }  // 确保返回的是更新后的文件
        );
        res.send({
            code: 200,
            data: updatedFile
        });
    } catch (error) {
        console.error('更新 like 时发生错误:', error);
        next(error);
    }
});


module.exports = app;
